/* -----------------------------------------------------------------------
 * Paul Cohen
 * CS 362, Summer 2014
 * Assignment 4
 *
 * randomtestcard.c - random tester for Dominion's Salvager card
 *
 * -----------------------------------------------------------------------
 */

#include "dominion.h"
#include "dominion_helpers.h"
#include "rngs.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

#define NUM_TESTS 10000

int main(int argc, char const *argv[])
{
    int i, j, numPlayers = 0, currentPlayer = 0;
    int deckCount = 0, handCount = 0, playedCount = 0, discardCount = 0;
    int cardChoice = 0, cardChoicePos = 0;
    int buysBefore = 0, coinsBefore = 0;
    int salvagerCardPos = 0;
    int success = 0;
    struct gameState G;

    SelectStream(2);
    PutSeed(time(NULL));

    for (i = 0; i < NUM_TESTS; i++)
    {
        // initialize/reset
        memset(&G, 0, sizeof(struct gameState));
        for (j = 0; j < sizeof(struct gameState); j++) {
          ((char*)&G)[j] = floor(Random() * 256);
        }
        G.numBuys = floor(Random() * 10);
        buysBefore = G.numBuys;

        // randomize elements (within reason)
        numPlayers = floor(Random() * 3) + 2;
        currentPlayer = floor(Random() * numPlayers);
        deckCount = floor(Random() * MAX_DECK) + 1;
        handCount = floor(Random() * MAX_HAND) + 1;
        playedCount = floor(Random() * MAX_DECK) + 1;
        discardCount = floor(Random() * MAX_DECK) + 1;
        coinsBefore = floor(Random() * 25);
        G.whoseTurn = currentPlayer;
        G.deckCount[currentPlayer] = deckCount;
        G.handCount[currentPlayer] = handCount;
        G.playedCardCount = playedCount;
        G.discardCount[currentPlayer] = discardCount;
        G.coins = coinsBefore;
        salvagerCardPos = floor(Random() * handCount); // hand position of Salvager card
        cardChoice = floor(Random() * 26);
        cardChoicePos = floor(Random() * handCount); // hand position of card choice
        if (handCount > 1)
        {
            while (salvagerCardPos == cardChoicePos)
            {
                cardChoicePos = floor(Random() * handCount);
            }
        }

        // fill deck with random cards
        for (j = 0; j < deckCount; j++)
        {
            G.deck[currentPlayer][j] = floor(Random() * 26);
        }
        // fill hand with random cards
        for (j = 0; j < handCount; j++)
        {
            G.hand[currentPlayer][j] = floor(Random() * 26);
        }

        G.hand[currentPlayer][salvagerCardPos] = salvager;
        G.hand[currentPlayer][cardChoicePos] = cardChoice;

        // run Salvager Card function
        success = cardEffect(salvager, cardChoicePos, 0, 0, &G, salvagerCardPos, 0);

        // test for correct amount of buys
        if (!(G.numBuys == buysBefore + 1))
        {
            printf("(Iteration %d) ERROR 1: number of buys is incorrect.\n", i);
            printf("Details:\n");
            printf("Number of players: %d\tCurrent player: %d\n", numPlayers, currentPlayer + 1);
            printf("Before Function:\tdeck count: %d, hand count: %d, number of buys: %d\n", deckCount, handCount, buysBefore);
            printf("After Function:\t\tdeck count: %d, hand count: %d, number of buys: %d\n", G.deckCount[currentPlayer], G.handCount[currentPlayer], G.numBuys);
            printf("------------\n");
        }

        // test for correct amount of coins
        if (!(G.coins == coinsBefore + getCost(cardChoice)) && success == 0)
        {
            printf("(Iteration %d) ERROR 2: number of coins is incorrect.\n", i);
            printf("Details:\n");
            printf("Number of players: %d\tCurrent player: %d\n", numPlayers, currentPlayer + 1);
            printf("Before Function:\tdeck count: %d, hand count: %d, number of coins: %d\n", deckCount, handCount, coinsBefore);
            printf("After Function:\t\tdeck count: %d, hand count: %d, number of coins: %d\n", G.deckCount[currentPlayer], G.handCount[currentPlayer], G.coins);
            printf("Card choice: %d (costs %d coins), card position: %d\n", cardChoice, getCost(cardChoice), cardChoicePos);
            printf("------------\n");
        }

        // test for correct amount of cards in played pile (makes sure one card is trashed)
        if (!(G.playedCardCount == playedCount + 1))
        {
            printf("(Iteration %d) ERROR 3: incorrect number of cards played.\n", i);
            printf("Details:\n");
            printf("Number of players: %d\tCurrent player: %d\n", numPlayers, currentPlayer + 1);
            printf("Before Function:\tdeck count: %d, hand count: %d, played count: %d\n", deckCount, handCount, playedCount);
            printf("After Function:\t\tdeck count: %d, hand count: %d, played count: %d\n", G.deckCount[currentPlayer], G.handCount[currentPlayer], G.playedCardCount);
            printf("------------\n");
        }

        // test for correct amount of cards in discard pile (should be 1, since one card is trashed)
        if (!(G.discardCount[currentPlayer] == discardCount + 1))
        {
            printf("(Iteration %d) ERROR 4: incorrect number of cards discarded.\n", i);
            printf("Details:\n");
            printf("Number of players: %d\tCurrent player: %d\n", numPlayers, currentPlayer + 1);
            printf("Before Function:\tdeck count: %d, hand count: %d, discard count: %d\n", deckCount, handCount, discardCount);
            printf("After Function:\t\tdeck count: %d, hand count: %d, discard count: %d\n", G.deckCount[currentPlayer], G.handCount[currentPlayer], G.discardCount[currentPlayer]);
            printf("------------\n");
        }
    }

    return 0;
}
